/*
 * =====================================================================================
 *
 *       Filename:  mini_tree.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  09/14/2012 07:14:17 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  baiyu (bekars), bekars@gmail.com
 *        Company:  BW
 *
 * =====================================================================================
 */

#include "mini_inc.h"
#include "mini_tree.h"

mini_tree_node_t *
mini_tree_create_node(int datalen)
{
    mini_tree_node_t *n = (mini_tree_node_t *)xmalloc(sizeof(mini_tree_node_t));
    if (!n) {
        mini_error("tree node create error !\n");
    }

    INIT_LIST_HEAD(&n->c);
    INIT_LIST_HEAD(&n->list);
    n->data = xmalloc(datalen);
    return n;
}

void
mini_tree_free_node(mini_tree_node_t **n)
{
    if (!*n) return;

    xlist_del(&(*n)->list);
    xfree((*n)->data);
    xfree((*n));
    (*n) = NULL;
}

void
mini_tree_free_tree(mini_tree_node_t *n)
{
    mini_tree_node_t *p = NULL;
    mini_tree_node_t *tmp = NULL;
    
    if (!n) return;
    
    xlist_for_each_entry_safe(p, tmp, &n->c, list) {
        mini_tree_free_tree(p);
    }

    if (xlist_empty(&n->c)) {
        mini_tree_free_node(&n);
    } else {
        mini_error("free tree error !\n");
    }
}

void
mini_tree_insert(mini_tree_node_t *f, mini_tree_node_t *c)
{
    xlist_add_tail(&c->list, &f->c);
    c->f = f;
}

mini_tree_node_t *
mini_tree_find(mini_tree_node_t *f, void *data, mini_tree_compare_pf compare)
{
    mini_tree_node_t *n = NULL;
    mini_tree_node_t *find = NULL;

    if (compare(f->data, data) == MINI_TREE_SAME) {
        return f;
    }

    xlist_for_each_entry(n, &f->c, list) {
        find = mini_tree_find(n, data, compare);
        if (find) return find;
    }
    return NULL;
}

mini_tree_node_t *
mini_tree_find_child(mini_tree_node_t *f, void *data, mini_tree_compare_pf compare)
{
    mini_tree_node_t *n = NULL;

    xlist_for_each_entry(n, &f->c, list) {
        if (compare(n->data, data) == MINI_TREE_SAME) {
            return n;
        }
    }
    return NULL;
}

int
mini_tree_list(mini_tree_node_t *n, mini_tree_call_pf call)
{
    mini_tree_node_t *p = NULL;

    if (call(n->data) == MINI_TREE_ERR) {
        return MINI_TREE_ERR;
    }

    xlist_for_each_entry(p, &n->c, list) {
        if (call(p->data) == MINI_TREE_ERR) {
            return MINI_TREE_ERR;
        }
    }

    return MINI_TREE_OK;
}


void
mini_tree_dump(mini_tree_node_t *f, mini_tree_show_pf show, int depth)
{
    int i;
    mini_tree_node_t *n = NULL;

    if (!f) printf("NULL NODE\n");

    //if (space) printf("  ");
    for (i = 0; i < depth; ++i) printf("    ");
    if (depth) printf("|--");

    show(f->data);

    xlist_for_each_entry(n, &f->c, list) {
        mini_tree_dump(n, show, depth + 1);
    }
}




